﻿#include "tcpwrap.h"

TcpWrap::TcpWrap(QObject *parent)
    : BaseRequester(parent)
{
}

void TcpWrap::setTcpSocket(QTcpSocket *socket)
{
    _tcpSocket = socket;
    connect(_tcpSocket, &QTcpSocket::readyRead, this, &TcpWrap::onReadyRead);
    connect(_tcpSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &TcpWrap::onError);
}

void TcpWrap::setKeepLiveData(QByteArray arr, int intervalMs)
{
    _keepLiveData = arr;
    _timer->setInterval(intervalMs);
}

void TcpWrap::startKeepLive()
{
    _timer->start();
}

void TcpWrap::stopKeepLive()
{
    _timer->stop();
}

bool TcpWrap::requestNoReply(QByteArray data)
{
    _recList.clear();
    return _tcpSocket->write(data) != -1;
}

bool TcpWrap::request(QByteArray data, QByteArray &rec)
{
    _recList.clear();
    _tcpSocket->write(data);

    QElapsedTimer ela;
    ela.start();
    while (_recList.count() == 0)
    {
        waitMs(100);
        if (ela.elapsed() > 3000)
        {
            QString ipPort=_tcpSocket->peerName()+":"+QString::number(_tcpSocket->peerPort());
            qDebug() << __FUNCTION__ << __LINE__ << QString("%1 time out").arg(ipPort)<<" "<<data.toHex();
            return false;
        }
    }
    waitMs(50);
    QByteArray arr;
    for (const auto &chunk : _recList)
    {
        arr.append(chunk);
    }
    rec = arr;
    return true;
}

void TcpWrap::waitMs(int ms)
{
    QEventLoop loop;
    QTimer::singleShot(ms, &loop, &QEventLoop::quit);
    loop.exec();
}

void TcpWrap::onError(QAbstractSocket::SocketError socketError)
{
    QString errString = _tcpSocket->errorString();
    qDebug() << __FUNCTION__ << __LINE__ << _tcpSocket->peerName() << socketError << errString;

    if (_tcpSocket->state() != QAbstractSocket::ConnectedState)
    {
        waitMs(500);
        _tcpSocket->abort();
        waitMs(500);
        _tcpSocket->connectToHost(_tcpSocket->peerName(), _tcpSocket->peerPort());
        bool ret = _tcpSocket->waitForConnected(3000);
        qDebug() << __FUNCTION__ << __LINE__ << "Reconnect:" << ret;
    }
}

void TcpWrap::onReadyRead()
{
    QByteArray arr = _tcpSocket->readAll();
    _recList.append(arr);
    emit receivedData(arr);
}
